/*
 * RobotBrain.java
 *
 * Created on September 9, 2006, 9:33 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package zh;

import java.awt.geom.Point2D;
import java.util.logging.Level;
import robocode.*;
import zh.logging.MyLogger;


/**
 *
 * @author zheismann
 */
public class RobotBrain
{
    private static RobotBrain instance;
    private static MyLogger logger = MyLogger.getLogger(RobotBrain.class.getName());
    static { logger.setEnabled(false); logger.setLevel(Level.FINE); }
    
    private UnderDog robot;
    private Navigator navigator;
    private TacticalAdvisor tacticalAdvisor;
    private boolean iWon;
    public static synchronized final RobotBrain getInstance(UnderDog r)
    {
        if (instance == null)
        {
            instance = new RobotBrain(r);
        }
        return instance;
    }
    private RobotBrain(UnderDog r)
    {
        this.robot = r;
        this.navigator = new Navigator(robot);
        this.tacticalAdvisor = new TacticalAdvisor(robot);
    }
    
    public void reset()
    {
        iWon = false;
    }
    /**
     * Based upon the current known state of affairs make a decision on
     * what to do next.
     *
     * All robot action calls made by Brain Subsystems should be non-blocking.
     *
     * Has an enemy been acquired?
     *    How recent is that information?
     * Should we try to update our information?
     * Where are we moving to?
     * Is the current target the best one?
     *      Should we be firing at it?
     */
    public void makeDecision()
    {
        if (!iWon && robot.doOtherOpponentsExist())
        {
            tacticalAdvisor.makeDecision();
            navigator.makeDecision();
        }
        else if (iWon)
        {
            robot.clearAllEvents();
            robot.doNothing();
        }
        robot.execute();
    }
    
    public void processEvent(ScannedRobotEvent event)
    {
        //THESE CALCULATIONS ARE CORRECT
        //THESE CALCULATIONS ARE CORRECT
        //THESE CALCULATIONS ARE CORRECT
        //THESE CALCULATIONS ARE CORRECT
        //THESE CALCULATIONS ARE CORRECT
		// Calculate enemy bearing
		double enemyBearing = robot.getHeading() + event.getBearing();
		// Calculate enemy's position
		double enemyX = event.getDistance() * Math.sin(Math.toRadians(enemyBearing));
        double enemyY = event.getDistance() * Math.cos(Math.toRadians(enemyBearing));
        Point2D enemyLocation = new Point2D.Double(robot.getX() + enemyX, robot.getY() + enemyY);
        logger.log(Level.FINEST, "\nprocessEvent(ScannedRobotEvent event)");
        logger.log(Level.FINEST, "enemyX: " + enemyX + " enemyY: " + enemyY + "  enemyBearing: " + enemyBearing);
        logger.log(Level.FINEST, "enemyLocation: " + enemyLocation);
        logger.log(Level.FINEST, "robot.getLocation(): " + robot.getLocation());
        logger.log(Level.FINEST, "robot.getHeading(): " + robot.getHeading() + "  event.getBearing(): " + event.getBearing());
        //THESE CALCULATIONS ARE CORRECT
        //THESE CALCULATIONS ARE CORRECT
        //THESE CALCULATIONS ARE CORRECT
        //THESE CALCULATIONS ARE CORRECT
        //THESE CALCULATIONS ARE CORRECT
        EnemyManager.getInstance().processEvent(event, enemyLocation);
        navigator.processEvent(event);
        tacticalAdvisor.processEvent(event);
        robot.execute();
        
        // always know where the other guy is
        
        // keep moving, goal is to avoid the other guy
        // take into account my location on the screen, where I'm heading
        
        // tactical decisions, am I close enough to fire knowing the other robot's 
        // current heading, speed, and my heading and speed how do I compensate to 
        // get a better shot?
        // as my energy decreases take a more conservative approach to firing
        // the higher probability the shot is the more power to put into it.
        
        // keep track of my current strategy's success, change strategy if I'm doing poorly.
        
        
    }
    public void processEvent(HitRobotEvent event)
    {
        tacticalAdvisor.processEvent(event);
        navigator.processEvent(event);
        robot.execute();
    }
    public void processEvent(HitWallEvent event)
    {
        navigator.processEvent(event);
        robot.execute();
    }
    
    public void processEvent(BulletMissedEvent event)
    {
        EnemyManager.getInstance().processEvent(event);
        tacticalAdvisor.processEvent(event);
    }
    public void processEvent(BulletHitEvent event)
    {
        EnemyManager.getInstance().processEvent(event);
    }    
    
    public void processEvent(HitByBulletEvent event)
    {
        navigator.processEvent(event);
        tacticalAdvisor.processEvent(event);
        robot.execute();
    }
    
    
    public void processEvent(CustomEvent event)
    {
        navigator.processEvent(event);
        tacticalAdvisor.processEvent(event);
    }
    
    public void processEvent(RobotDeathEvent event)
    {
        EnemyManager.getInstance().processEvent(event);
        tacticalAdvisor.processEvent(event);
        robot.execute();
    }
    
    public void processEvent(DeathEvent event)
    {
        tacticalAdvisor.processEvent(event);
        navigator.processEvent(event);
        EnemyManager.getInstance().processEvent(event);
        robot.execute();
    }
    public void processEvent(WinEvent event)
    {
        iWon = true;
        tacticalAdvisor.processEvent(event);
        navigator.processEvent(event);
        EnemyManager.getInstance().processEvent(event);
        robot.execute();
    }
    
    public void onPaint(java.awt.Graphics2D g)
    {
        tacticalAdvisor.onPaint(g);
        navigator.onPaint(g);
    }
}
